package com.turbo.cloud.ods.utils.data;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.turbo.cloud.core.annotations.datamasking.DataMaskingType;
import com.turbo.cloud.core.annotations.datamasking.masker.Masker;
import com.turbo.cloud.core.annotations.dict.translator.Translator;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * SQL解析
 *
 * @author zhangluning
 */
@Slf4j
public class DataUtil {

    /**
     * 时间格式
     */
    final static String PATTERN_DATE_TIME = "yyyy-MM-dd HH:mm:ss";

    /**
     * 检查SQL
     *
     * @param sourceMapPage 数据源MapPage
     * @param formatRule    数据格式化规则
     */
    public static void formatMapPageData(Page<Map<String, Object>> sourceMapPage, String formatRule) {
        formatMapListData(sourceMapPage.getRecords(), formatRule);
    }

    /**
     * 检查SQL
     *
     * @param sourceMapList 数据源MapList
     * @param formatRule    数据格式化规则
     */
    public static void formatMapListData(List<Map<String, Object>> sourceMapList, String formatRule) {
        if (!CollectionUtils.isEmpty(sourceMapList)) {
            List<DataFormatRule> formatRules = JSON.parseArray(formatRule, DataFormatRule.class);
            for (Map<String, Object> map : sourceMapList) {
                formatMapData(map, formatRules);
            }
        }
    }

    /**
     * 检查SQL
     *
     * @param sourceMap  数据源MAP
     * @param formatRule 数据格式化规则
     */
    public static void formatMapData(Map<String, Object> sourceMap, String formatRule) {
        List<DataFormatRule> formatRules = JSON.parseArray(formatRule, DataFormatRule.class);
        formatMapData(sourceMap, formatRules);
    }

    /**
     * 检查SQL
     *
     * @param sourceMap   数据源MAP
     * @param formatRules 数据格式化规则
     */
    public static void formatMapData(Map<String, Object> sourceMap, List<DataFormatRule> formatRules) {
        if (Objects.isNull(sourceMap) || Objects.isNull(formatRules)) {
            return;
        }
        for (DataFormatRule dataFormatRule : formatRules) {
            Object dataObjectValue = sourceMap.get(dataFormatRule.getColumnCode());

            String dataValue = null;
            if (Objects.nonNull(dataObjectValue)) {
                if (dataObjectValue instanceof String) {
                    dataValue = (String) dataObjectValue;
                } else if (dataObjectValue instanceof Integer) {
                    dataValue = String.valueOf(dataObjectValue);
                } else if (dataObjectValue instanceof Long) {
                    dataValue = String.valueOf(dataObjectValue);
                } else if (dataObjectValue instanceof Double) {
                    dataValue = String.valueOf(dataObjectValue);
                } else if (dataObjectValue instanceof Float) {
                    dataValue = String.valueOf(dataObjectValue);
                } else if (dataObjectValue instanceof BigDecimal) {
                    dataValue = String.valueOf(dataObjectValue);
                } else if (dataObjectValue instanceof Boolean) {
                    dataValue = String.valueOf(dataObjectValue);
                } else if (dataObjectValue instanceof Date || dataObjectValue instanceof LocalDateTime) {
                    // 日期字符串的格式
                    SimpleDateFormat dateFormat = new SimpleDateFormat(PATTERN_DATE_TIME);
                    dataValue = dateFormat.format(dataObjectValue);
                }
            }
            if (Objects.nonNull(dataValue) && StrUtil.isNotBlank(dataFormatRule.getFormatRuleClass())) {
                String dataNewValue = null;
                // 转化类型
                String formatRuleType = dataFormatRule.getFormatRuleType();
                // 转化规则
                String formatRuleClass = dataFormatRule.getFormatRuleClass();
                // 转化规则
                String formatRulePhrase = dataFormatRule.getFormatRulePhrase();

                if (DataFormatRuleEnum.DICT.name().equals(formatRuleType)) {
                    Translator translator = SpringUtil.getBean(formatRuleClass);
                    dataNewValue = translator.translate(dataValue);
                } else if (DataFormatRuleEnum.MASK.name().equals(formatRuleType)) {
                    Masker masker = SpringUtil.getBean(formatRuleClass);
                    dataNewValue = masker.masking(DataMaskingType.findByValue(formatRulePhrase), dataValue);
                } else if (DataFormatRuleEnum.DATETIME.name().equals(formatRuleType)) {
                    if (PATTERN_DATE_TIME.equals(formatRulePhrase)) {
                        dataNewValue = dataValue;
                    } else {
                        SimpleDateFormat sdf = new SimpleDateFormat(formatRulePhrase);
                        try {
                            Date date = sdf.parse(dataValue);
                            dataNewValue = sdf.format(date);
                        } catch (ParseException e) {
                            log.error("报表字段时间格式转化异常", e);
                            dataNewValue = "DateTime Translate Error";
                        }
                    }
                } else if (DataFormatRuleEnum.MONEY.name().equals(formatRuleType)) {
                    Double money = Double.parseDouble(dataValue);
                    DecimalFormat decimalFormat = new DecimalFormat(formatRulePhrase);
                    dataNewValue = decimalFormat.format(money);
                } else if (DataFormatRuleEnum.RMB_CN.name().equals(formatRuleType)) {
                    // 保留两位小数并且四舍五入
                    BigDecimal bigDecimal = new BigDecimal(dataValue).setScale(2, RoundingMode.HALF_UP);
                    dataNewValue = Convert.digitToChinese(bigDecimal);
                }

                sourceMap.put(dataFormatRule.getColumnCode(), dataNewValue);
            }
        }
    }
}
